package com._21cn.cms.article.web.servlet;

import com._21cn.cms.article.entity.Article;
import com._21cn.cms.common.Constants;
import com._21cn.cms.common.utils.ResponseUtil;
import com._21cn.cms.site.entity.Column;
import com._21cn.cms.site.entity.Site;
import com._21cn.cms.site.service.ColumnService;
import com._21cn.cms.site.service.SiteService;
import com._21cn.cms.template.utils.TemplateHelper;
import com._21cn.framework.http.HttpResponseUtil;
import com._21cn.framework.utils.StringUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Thinkpad on 2017/4/15.
 */
public class ArticleViewServlet extends HttpServlet {

    private static final Logger log = LoggerFactory.getLogger(ArticleViewServlet.class);

    private static Pattern urlPattern = Pattern.compile("/(\\d{4})/(\\d{4})/(\\d{2})/(\\d{1,10})\\.shtml");
    private static Pattern urlPatternWithPage = Pattern.compile("/(\\d{4})/(\\d{4})/(\\d{2})/(\\d{1,10})_(\\d{1,2}|all)\\.shtml");

    private static List<String> clientCodeList = new ArrayList<String>();
    static {
        clientCodeList.add(com._21cn.cms.article.Constants.CLIENT_CODE_PC);
        clientCodeList.add(com._21cn.cms.article.Constants.CLIENT_CODE_WAP);
        clientCodeList.add(com._21cn.cms.article.Constants.CLIENT_CODE_APP);
    }

    private ColumnService columnService;

    private SiteService siteService;

    private TemplateHelper templateHelper;

//    private SsiProcessor ssiProcessor;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletConfig.getServletContext());
        templateHelper = (TemplateHelper) wac.getBean("templateHelper");
        columnService = (ColumnService) wac.getBean("columnService");
        siteService = (SiteService) wac.getBean("siteService");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response){
        int articleId = 0;
        String pageNo = "0".intern();

        Matcher regexpMatcher = urlPattern.matcher(request.getRequestURL());
        if (regexpMatcher.find()) {
            articleId = Integer.parseInt(regexpMatcher.group(4));
        } else {
            Matcher regexpMatcherWithPage = urlPatternWithPage.matcher(request.getRequestURL());
            if (regexpMatcherWithPage.find()) {
                articleId = Integer.parseInt(regexpMatcherWithPage.group(4));
                pageNo = regexpMatcherWithPage.group(5);
            }
        }

        if (articleId == 0) {
            response.setStatus(404);
            ResponseUtil.returnMsg(response, "404 not found page!");
            return;
        }

        try {
            response.setCharacterEncoding("utf8");
            response.setContentType("text/html");
            String domain = request.getServerName();
            String pathInfo = request.getRequestURL().substring(request.getRequestURL().lastIndexOf(domain) + domain.length());

            String columnPath = domain + pathInfo;
            String[] columnPaths = columnPath.split("/");
            int length = columnPaths.length - 5;
            columnPaths = Arrays.copyOf(columnPaths, length);

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < columnPaths.length; i++) {
                if (i != columnPaths.length - 1) {
                    sb.append(columnPaths[i]).append("/");
                } else {
                    sb.append(columnPaths[i]);
                }
            }

            columnPath = sb.toString();
            String url = "http://"+columnPath;
            Column column = columnService.getColumnByUrl(url);

            if (column == null) {
                response.setStatus(404);
                ResponseUtil.returnMsg(response, "404 not found page!");
                return;
            }

            Site site = siteService.getById(column.getSiteId());

            if (site == null) {
                response.setStatus(404);
                ResponseUtil.returnMsg(response, "404 not found page!");
                return;
            }

            String clientCode = pathInfo.substring(columnPath.length() - domain.length()).split("/")[1];

            int lastIndexOfDot = pathInfo.lastIndexOf(".");
            if (lastIndexOfDot == -1) {
                response.setStatus(404);
                ResponseUtil.returnMsg(response, "404 not found page!");
                return;
            }
            Article article = null;
            try {
                String jsonPath = Constants.DEFAULT_FILE_PATH + "/" + site.getCode() + "/article/" + domain + "/" +
                        pathInfo.substring(columnPath.length() - domain.length(), pathInfo.lastIndexOf("/")).replace("/" + clientCode + "/", "") + "/" + articleId + ".json";
                File jsonFile = new File(jsonPath);
                article = JSON.parseObject(FileUtils.readFileToString(jsonFile, "utf8"), Article.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (article != null) {
                if (!article.getPublishStatus().equals(com._21cn.cms.article.Constants.PUBLISH_STATUS_DONE)
                        && !article.getPublishStatus().equals(com._21cn.cms.article.Constants.PUBLISH_STATUS_FETCH_DONE)) {
                    response.setStatus(404);
                    ResponseUtil.returnMsg(response, "404 not found page!");
                    return;
                }
            } else {
                response.setStatus(404);
                ResponseUtil.returnMsg(response, "404 not found page!");
                return;
            }

            if(!clientCodeList.contains(clientCode)){
                response.setStatus(404);
                ResponseUtil.returnMsg(response, "404 not found page!");
                return;
            }

            String content = getResultContent(article, clientCode, pageNo);
            HttpResponseUtil.setCacheHeader(response, 60, article.getModifyTime());
            ResponseUtil.returnMsg(response, content);
            return;

        }catch ( Exception e){
            e.printStackTrace();
            ResponseUtil.returnMsg(response, "404 not found page!");
            log.error("error , url:" + request.getRequestURL());
        }

    }

    private String getResultContent(Article article, String clientCode, String pageNo){
        String content = "";
        int pageNo_int = pageNo.equals("all") ? -1 : Integer.parseInt(pageNo);
        String cacheFilePath = templateHelper.getArticleStaticFilePath(article, clientCode);
        String cacheFilePathWithPageNo = pageNo_int != 0 ? cacheFilePath.replace(".shtml", "_" + pageNo + ".shtml") : cacheFilePath;
        File cacheFile = new File(cacheFilePathWithPageNo);
        if (!cacheFile.exists()) {
            List<String> result = templateHelper.generateArticle(article, clientCode);
            if (result != null && result.size() > 0) {
                if (pageNo_int == -1)
                    content = result.get(result.size() - 1);
                else if( pageNo_int < result.size()){
                    content = result.get(pageNo_int);
                }
                return content;
            } else {
                log.error("contentList== null && contentList.size() <= 0, path:" + cacheFile );
            }
        }
        try {
            content = FileUtils.readFileToString(cacheFile, "utf8");
            return content;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

}
